<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图片拖动js</title>
    <style>
        * { margin:0; padding:0; }
        div { width:600px; height:400px; background:#FFF; border:1px solid slateblue; position:relative; overflow:hidden; margin:20px auto; }
        img { position:absolute; left:0; top:0; transform:scale(1); }
        img:active { cursor:move; }
        ::-webkit-scrollbar { width:6px; height:6px; background-color:#F5F5F5; }
        ::-webkit-scrollbar-thumb { background-color:#3d4a5dd9; }
        ::-webkit-scrollbar-track { -webkit-box-shadow:inset 0 0 6px rgba(0, 0, 0, 0.3); box-shadow:inset 0 0 6px rgba(0, 0, 0, 0.3); background-color:#F5F5F5; }
    </style>
</head>
<body>
<div id="dragImage"></div>

<script>
    document.addEventListener("DOMContentLoaded", function() {
        class DRAGIMAGE {
            constructor({ dom, img, zoomMax, zoomMin }) {
                let that = this;
                this.dom = dom;                        // dom
                this.dom.innerHTML = `<img src="${img}" draggable="false" />`;  // 图片放进盒子
                this.img = dom.querySelector("img");   // img
                this.startX = 0;                      // 鼠标起始坐标x
                this.startY = 0;                      // 鼠标起始坐标y
                this.moveLeft = 0;                    // 鼠标向左移动距离
                this.moveTop = 0;                     // 鼠标向上移动距离
                this.imgLeft = 0;                     // 图片当前定位 left
                this.imgTop = 0;                      // 图片当前定位 top
                this.imgWidth = 0;                    // 图片实际宽度
                this.imgHeight = 0;                   // 图片实际高度
                this.domWidth = dom.offsetWidth;      // 父盒子宽度
                this.domHeight = dom.offsetHeight;    // 父盒子高度
                this.zoom = 100;                      // 缩放大小 100 正常大小
                this.zoomMax = (zoomMax * 100) || 200;  // 最大缩放
                this.zoomMin = (zoomMin * 100) || 0.5;  // 最小缩放

                this.isDrag = false // 是否拖动

                var image = new Image();
                image.src = img;
                image.onload = function() {
                    // 获取到图片实际宽高
                    that.imgWidth = image.width;
                    that.imgHeight = image.height;
                    // 鼠标按下执行
                    that.mouseDown();
                }
                // 滚轮事件 放大缩小图片
                that.mouseWheel();
                // 鼠标抬起 清除移动事件
                dom.addEventListener("mouseup", function(e) { console.log('鼠标抬起');that.isDrag = false;  that.stopmove() });
                // 鼠标移出父盒子 清除移动事件
                dom.addEventListener("mouseout", function(e) { console.log('鼠标移出父盒子');that.isDrag = false; that.stopmove() });
            }
            /*
                鼠标按下时触发
                获取鼠标在图片内的坐标
            */
            mouseDown() {
                let that = this;
                this.img.addEventListener("mousedown", function(e) {
                    console.log('鼠标点击图片')
                    that.isDrag = true
                    e = e || event;
                    // 获取起始坐标
                    that.startX = e.clientX;
                    that.startY = e.clientY;
                    // 鼠标移动
                    that.mouseMove();
                    return false;
                });
            }
            /*
                鼠标移动事件
                获取鼠标在图内的移动距离: 图片当前定位 - ( 起始坐标 - 当前坐标 )
            */
            mouseMove() {
                let that = this;
                this.dom.addEventListener("mousemove", function(e) {
                    e = e || event;
                    /* 获取鼠标移动距离 */
                    that.moveLeft = that.imgLeft - (that.startX - e.clientX);
                    that.moveTop = that.imgTop - (that.startY - e.clientY);

                    // 随鼠标移动 更新图片定位
                    if(that.isDrag){
                        that.setPosition();
                    }

                    return false;
                });
            }
            /*
                滚轮事件 放大缩小图片
            */
            mouseWheel() {
                let that = this;
                this.dom.addEventListener("wheel", function(e) {
                    e = e || event;
                    e.stopPropagation();
                    e.preventDefault();
                    let width, height;
                    // 判断上下滚动 chrome & ie || firefox
                    var delta = (e.wheelDelta && (e.wheelDelta > 0 ? 1 : -1)) || (e.detail && (e.detail > 0 ? -1 : 1));
                    // delta > 0 上滚 ，delta < 0 下滚
                    if (delta > 0) {
                        ++that.zoom;
                        if (that.zoom >= that.zoomMax)
                            that.zoom = that.zoomMax; // 限制最大缩放
                        if (that.zoom <= that.zoomMax)
                            width = that.imgWidth * ((that.zoom) / 100);
                        height = that.imgHeight * ((that.zoom) / 100);
                    } else if (delta < 0) {
                        --that.zoom;
                        if (that.zoom <= that.zoomMin)
                            that.zoom = that.zoomMin; // 限制最小缩放
                        if (that.zoom >= that.zoomMin)
                            width = that.imgWidth * ((that.zoom) / 100);
                        height = that.imgHeight * ((that.zoom) / 100);
                    }
                    that.scaleImg({ width, height }); // 对图片进行缩放
                    // that.setPosition();
                    return false;
                });
            }
            /*
                通过改变 width/height 进行缩放
            */
            scaleImg({ width, height }) {
                this.img.style.width = width + "px";
                this.img.style.height = height + "px";
            }
            /*
                设置图片定位, 边界限制
                    左/上限制：图片当前宽高 大于/小于 父盒子的宽高
                        鼠标移动距离 = 0
                    右/下限制：(鼠标移动距离-父盒子最大宽高)大于当前图片宽高 || 鼠标移动距离大于 -(当前图片宽高-父盒子最大宽高)
                        鼠标移动距离 = -(当前图片宽高 - 父盒子宽高);
            */
            setPosition() {
                let that = this;
                // 图片当前宽高大于父盒子的宽高 || 图片当前宽高小于父盒子的宽高
                /* 左/上 */
                if (that.moveLeft >= 0 && that.img.offsetWidth > that.domWidth || that.moveLeft <= 0 && that.img.offsetWidth < that.domWidth)
                    that.moveLeft = 0;
                if (that.moveTop >= 0 && that.img.offsetHeight > that.domHeight || that.moveTop <= 0 && that.img.offsetHeight < that.domHeight)
                    that.moveTop = 0;
                /* 右/下 */
                if (Math.abs((that.moveLeft - that.domWidth)) >= that.img.offsetWidth && that.img.offsetWidth > that.domWidth || that.moveLeft >= (-(that.img.offsetWidth - that.domWidth)) && that.img.offsetWidth < that.domWidth)
                    that.moveLeft = -(that.img.offsetWidth - that.domWidth);
                if (Math.abs((that.moveTop - that.domHeight)) >= that.img.offsetHeight && that.img.offsetHeight > that.domHeight || that.moveTop >= (-(that.img.offsetHeight - that.domHeight)) && that.img.offsetHeight < that.domHeight)
                    that.moveTop = -(that.img.offsetHeight - that.domHeight);
                // 定位移动的距离 = 鼠标移动的距离
                that.img.style.left = that.moveLeft + "px";
                that.img.style.top = that.moveTop + "px";
            }
            // 停止鼠标移动
            stopmove() {
                /* 清除移动事件，绑定图片当前定位 */
                let that = this;
                this.dom.removeEventListener("mousemove", function(e) { that.mouseMove(e) });//删除不了
                this.imgLeft = parseInt(this.img.style.left) || 0;
                this.imgTop = parseInt(this.img.style.top) || 0;
            }
        }

        var dragImage = new DRAGIMAGE({
            dom: document.querySelector('#dragImage'), // 图片的父元素
            img: "https://webstatic.mihoyo.com/upload/op-public/2023/05/30/ac698e2d5ea0f66317d189d7697a5d04_1233201386636480873.png", // 图片路径
            zoomMax: 4, // 缩放最大倍数，1正常大小
            zoomMin: 0.2 // 缩放最小倍数，1正常大小
        });
    });




</script>
</body>
</html>
